﻿using System;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.ComponentModel;
using MaterialDesignThemes.Wpf;

namespace RotovapPlatform.UI.Controls
{
	/// <summary>
	/// NumericTextBox.xaml 的交互逻辑
	/// </summary>
	public partial class NumericTextBox : UserControl
	{
		private static readonly Regex _numericRegex = new Regex(@"^[0-9]*(?:\.[0-9]*)?$");
		private bool _isInternalUpdate = false;

		#region 依赖属性

		/// <summary>
		/// 值
		/// </summary>
		public static readonly DependencyProperty ValueProperty =
			DependencyProperty.Register("Value", typeof(double), typeof(NumericTextBox),
				new PropertyMetadata(0.0, OnValueChanged));

		/// <summary>
		/// 值变更回调
		/// </summary>
		private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			if (d is NumericTextBox textBox && !textBox._isInternalUpdate)
			{
				textBox._isInternalUpdate = true;
				textBox.PART_TextBox.Text = e.NewValue.ToString();
				textBox._isInternalUpdate = false;
			}
		}

		/// <summary>
		/// 最小值
		/// </summary>
		public static readonly DependencyProperty MinValueProperty =
			DependencyProperty.Register("MinValue", typeof(double), typeof(NumericTextBox), new PropertyMetadata(double.MinValue, OnRangeChanged));

		/// <summary>
		/// 最大值
		/// </summary>
		public static readonly DependencyProperty MaxValueProperty =
			DependencyProperty.Register("MaxValue", typeof(double), typeof(NumericTextBox), new PropertyMetadata(double.MaxValue, OnRangeChanged));

		/// <summary>
		/// 提示文本
		/// </summary>
		public static readonly DependencyProperty HintProperty =
			DependencyProperty.Register("Hint", typeof(string), typeof(NumericTextBox), new PropertyMetadata(string.Empty));

		/// <summary>
		/// 错误消息
		/// </summary>
		public static readonly DependencyProperty ErrorMessageProperty =
			DependencyProperty.Register("ErrorMessage", typeof(string), typeof(NumericTextBox), new PropertyMetadata("值必须在 {0} 和 {1} 之间", OnRangeChanged));

		/// <summary>
		/// 单位
		/// </summary>
		public static readonly DependencyProperty UnitProperty =
			DependencyProperty.Register("Unit", typeof(string), typeof(NumericTextBox), new PropertyMetadata(string.Empty));

		/// <summary>
		/// 属性变更回调
		/// </summary>
		private static void OnRangeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			if (d is NumericTextBox textBox)
			{
				textBox.UpdateProxyData();
			}
		}

		#endregion

		#region 属性

		/// <summary>
		/// 值
		/// </summary>
		public double Value
		{
			get { return (double)GetValue(ValueProperty); }
			set { SetValue(ValueProperty, value); }
		}

		/// <summary>
		/// 最小值
		/// </summary>
		public double MinValue
		{
			get { return (double)GetValue(MinValueProperty); }
			set { SetValue(MinValueProperty, value); }
		}

		/// <summary>
		/// 最大值
		/// </summary>
		public double MaxValue
		{
			get { return (double)GetValue(MaxValueProperty); }
			set { SetValue(MaxValueProperty, value); }
		}

		/// <summary>
		/// 提示文本
		/// </summary>
		public string Hint
		{
			get { return (string)GetValue(HintProperty); }
			set { SetValue(HintProperty, value); }
		}

		/// <summary>
		/// 错误消息
		/// </summary>
		public string ErrorMessage
		{
			get { return (string)GetValue(ErrorMessageProperty); }
			set { SetValue(ErrorMessageProperty, value); }
		}

		/// <summary>
		/// 单位
		/// </summary>
		public string Unit
		{
			get { return (string)GetValue(UnitProperty); }
			set { SetValue(UnitProperty, value); }
		}

		#endregion

		public NumericTextBox()
		{
			InitializeComponent();

			// 加载时更新代理对象的数据
			Loaded += (s, e) => UpdateProxyData();

			// 添加获得焦点事件处理
			PART_TextBox.GotFocus += PART_TextBox_GotFocus;

			// 添加失去焦点事件处理
			PART_TextBox.LostFocus += PART_TextBox_LostFocus;
		}

		/// <summary>
		/// 更新代理对象的数据
		/// </summary>
		private void UpdateProxyData()
		{
			if (Resources.Contains("MinValueProxy"))
			{
				var minValueProxy = Resources["MinValueProxy"] as Validation.DependencyObjectProxy;
				if (minValueProxy != null)
				{
					minValueProxy.Data = MinValue;
				}
			}

			if (Resources.Contains("MaxValueProxy"))
			{
				var maxValueProxy = Resources["MaxValueProxy"] as Validation.DependencyObjectProxy;
				if (maxValueProxy != null)
				{
					maxValueProxy.Data = MaxValue;
				}
			}

			if (Resources.Contains("ErrorMessageProxy"))
			{
				var errorMessageProxy = Resources["ErrorMessageProxy"] as Validation.DependencyObjectProxy;
				if (errorMessageProxy != null)
				{
					errorMessageProxy.Data = ErrorMessage;
				}
			}
		}

		/// <summary>
		/// 文本输入预览事件处理
		/// </summary>
		private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
		{
			// 获取当前文本和新输入的文本
			TextBox textBox = sender as TextBox;
			string newText = textBox.Text.Insert(textBox.CaretIndex, e.Text);

			// 验证是否为有效的数字格式
			e.Handled = !IsValidNumericInput(newText);
		}

		/// <summary>
		/// 验证输入是否为有效的数字格式
		/// </summary>
		private bool IsValidNumericInput(string text)
		{
			return _numericRegex.IsMatch(text);
		}

		/// <summary>
		/// 文本变更事件处理
		/// </summary>
		private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
		{
			if (_isInternalUpdate) return;

			// 在输入过程中不验证范围，只在失去焦点时验证
			// 这样用户可以输入任何值，只有在完成输入后才会验证

			// 尝试将文本转换为数值并更新Value属性
			if (sender is TextBox textBox && !string.IsNullOrEmpty(textBox.Text))
			{
				if (double.TryParse(textBox.Text, out double value))
				{
					_isInternalUpdate = true;
					Value = value;
					_isInternalUpdate = false;
				}
			}
		}

		/// <summary>
		/// 输入框获得焦点事件处理
		/// </summary>
		private void PART_TextBox_GotFocus(object sender, RoutedEventArgs e)
		{
			// 在获得焦点时，显示范围提示
			if (sender is TextBox textBox)
			{
				// 使用MaterialDesignInXAML的HintAssist.HelperText显示范围提示
				HintAssist.SetHelperText(textBox, $"范围: {MinValue} - {MaxValue} {Unit}");
			}
		}

		/// <summary>
		/// 输入框失去焦点事件处理
		/// </summary>
		private void PART_TextBox_LostFocus(object sender, RoutedEventArgs e)
		{
			// 在失去焦点时，清除范围提示并验证范围
			if (sender is TextBox textBox)
			{
				HintAssist.SetHelperText(textBox, null);

				// 如果文本为空，不进行处理
				if (string.IsNullOrEmpty(textBox.Text))
					return;

				// 尝试解析为数值
				if (double.TryParse(textBox.Text, out double value))
				{
					// 如果超出范围，自动调整到范围内
					if (value < MinValue)
					{
						value = MinValue;
						textBox.Text = MinValue.ToString();
					}
					else if (value > MaxValue)
					{
						value = MaxValue;
						textBox.Text = MaxValue.ToString();
					}

					// 更新Value属性
					_isInternalUpdate = true;
					Value = value;
					_isInternalUpdate = false;
				}
			}
		}
	}
}